#include "SpriteManager.h"

// Initialize the instance to null
SpriteManager* SpriteManager::m_SpriteInstance = 0;

SpriteManager::SpriteManager(void)
{
	sSpriteIndex = 0;
}

SpriteManager::~SpriteManager(void)
{
}

SpriteManager* SpriteManager::GetInstance(void)
{
	// Create the singleton if it doesn't exist
	if(!m_SpriteInstance)
		m_SpriteInstance = new SpriteManager;

	// Return the singleton
	return m_SpriteInstance;
}

void SpriteManager::DeleteSpriteInstance(void)
{
	SpriteManager::DestroyAllSprites();
	SpriteManager::ShutdownDevice();
	// If instance exist, delete it!
	if(m_SpriteInstance)
	{
		delete m_SpriteInstance;
		m_SpriteInstance = NULL;
	}
}

void SpriteManager::InitSpriteManager(IDirect3DDevice9* m_pD3DDevice)
{
	// Get the device
	m_Device = m_pD3DDevice;

	// Load D3DX Sprite COM object
	HRESULT result;
	result = D3DXCreateSprite(m_pD3DDevice, &m_pD3DSprite);
}

short SpriteManager::LoadSprite(LPCSTR spriteFilename, D3DXVECTOR3 vecPos, float fScale)
{
	// Create the current sprite structure we are loading
	s_Sprite* currentSprite = new s_Sprite;

	// Actually create the sprite texture
	D3DXCreateTextureFromFileEx(
		m_Device, spriteFilename, 0, 0, 0, 0, D3DFMT_UNKNOWN,
		D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(250, 3, 240),
		&(currentSprite->m_ImageInfo), NULL, &(currentSprite->m_pD3DTexture));

	// Set this current sprites attributes
	currentSprite->vecPos = vecPos;
	currentSprite->fScale = fScale;
	currentSprite->vecCenter = D3DXVECTOR3((float)(currentSprite->m_ImageInfo.Width/2), (float)(currentSprite->m_ImageInfo.Height/2), 0.0f);
	currentSprite->vecRot = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	currentSprite->color = D3DCOLOR_ARGB(255, 255, 255, 255);

	// Insert the current structure into the vector
	spriteList.push_back(currentSprite);

	return sSpriteIndex++;
}

void SpriteManager::DrawSprite(short sSpriteID)
{
	D3DXMATRIX worldMat, scaleMat, rotMat, transMat;

	// Move and draw the sprites
	D3DXMatrixIdentity(&worldMat);
	D3DXMatrixIdentity(&scaleMat);
	D3DXMatrixIdentity(&rotMat);
	D3DXMatrixIdentity(&transMat);

	D3DXMatrixScaling(&scaleMat, spriteList[sSpriteID]->fScale, spriteList[sSpriteID]->fScale, spriteList[sSpriteID]->fScale);
	D3DXMatrixRotationYawPitchRoll(&rotMat, spriteList[sSpriteID]->vecRot.x, spriteList[sSpriteID]->vecRot.y, spriteList[sSpriteID]->vecRot.z);
	D3DXMatrixTranslation(&transMat, spriteList[sSpriteID]->vecPos.x, spriteList[sSpriteID]->vecPos.y, spriteList[sSpriteID]->vecPos.z);
	D3DXMatrixMultiply(&scaleMat, &rotMat, &scaleMat);
	D3DXMatrixMultiply(&worldMat, &scaleMat, &transMat);

	m_pD3DSprite->SetTransform(&worldMat);

	if(SUCCEEDED(m_pD3DSprite->Begin(D3DXSPRITE_ALPHABLEND)))
	{
		// Draw the sprite
		m_pD3DSprite->Draw(spriteList[sSpriteID]->m_pD3DTexture, NULL, &(spriteList[sSpriteID]->vecCenter), NULL, spriteList[sSpriteID]->color);

		m_pD3DSprite->End();
	}
}

void SpriteManager::ModifySpritePos(short sSpriteID, float fXChange, float fYChange)
{
	spriteList[sSpriteID]->vecPos.x = fXChange;
	spriteList[sSpriteID]->vecPos.y = fYChange;
}

void SpriteManager::ModifySpriteRot(short sSpriteID, float fZChange)
{
	spriteList[sSpriteID]->vecRot.z += fZChange;
}

bool SpriteManager::SpriteCollision(short sSpriteID, POINT pMousePoint)
{
	// see if the point is within the Sprite
	// Sprites are drawn with the position as the
	// *center* of the sprite
	// Notice the allowances for drawing errors
	if( pMousePoint.x - 4 < (spriteList[sSpriteID]->vecPos.x - spriteList[sSpriteID]->vecCenter.x * spriteList[sSpriteID]->fScale))
		return false;
	if( pMousePoint.x - 4 > (spriteList[sSpriteID]->vecPos.x + spriteList[sSpriteID]->vecCenter.x * spriteList[sSpriteID]->fScale))
		return false;
	if( pMousePoint.y - 22 < (spriteList[sSpriteID]->vecPos.y - spriteList[sSpriteID]->vecCenter.y * spriteList[sSpriteID]->fScale))
		return false;
	if( pMousePoint.y - 22 > (spriteList[sSpriteID]->vecPos.y + spriteList[sSpriteID]->vecCenter.y * spriteList[sSpriteID]->fScale))
		return false;
	
	// otherwise, we have collision
	return true;
}

short SpriteManager::GetSpriteCount()
{
	return sSpriteIndex;
}

void SpriteManager::DestroySprite(short sSpriteID)
{
	spriteList[sSpriteID]->m_pD3DTexture->Release();
	delete spriteList[sSpriteID];
	spriteList[sSpriteID] = NULL;
	spriteList.pop_back();
	sSpriteIndex--;
}

void SpriteManager::DestroyAllSprites(void)
{
	for(int i = sSpriteIndex - 1; i >= 0; i--)
	{
		spriteList[i]->m_pD3DTexture->Release();
		delete spriteList[i];
		spriteList[i] = NULL;
		spriteList.pop_back();
	}
	sSpriteIndex = 0;
}

void SpriteManager::ShutdownDevice(void)
{
	if(m_pD3DSprite)
	{
		m_pD3DSprite->Release();
		m_pD3DSprite = NULL;
	}
}